export type bool = 0 | 1;

export type Collection<T> = { [key: string]: T };
export type Col<T> = Collection<T>;

// export type AttrData = {} | number | string | boolean | AttrData[];
export type AttrData = number | string | bool | boolean;
export type ShaderAttribute = number | cc.Vec2 | cc.Vec3 | cc.Vec4 | cc.Color;

export abstract class CloneAble {
    abstract clone(): CloneAble;
};

export class CtrlInfo {
    btn = 0b0;
    protected _setBit(bit, bool) {
        if (bool) {
            this.btn |= bit;
        }
        else if ((this.btn | bit) == this.btn) {
            this.btn ^= bit;
        }
    }
};

export class KeyboardInfo extends CtrlInfo {
    static readonly BIT_CTRL = 0b1;
    static readonly BIT_SHIFT = 0b10;
    static readonly BIT_ALT = 0b100;

    lastDownKeyCode = 0;
    lastUpKeyCode = 0;

    get btnCTRL() {
        return (this.btn | KeyboardInfo.BIT_CTRL) == this.btn;
    }
    set btnCTRL(bool) {
        this._setBit(KeyboardInfo.BIT_CTRL, bool);
    }
    get btnALT() {
        return (this.btn | KeyboardInfo.BIT_ALT) == this.btn;
    }
    set btnALT(bool) {
        this._setBit(KeyboardInfo.BIT_ALT, bool);
    }
    get btnSHIFT() {
        return (this.btn | KeyboardInfo.BIT_SHIFT) == this.btn;
    }
    set btnSHIFT(bool) {
        this._setBit(KeyboardInfo.BIT_SHIFT, bool);
    }
};

export class MouseInfo extends CtrlInfo {
    static readonly BIT_BTN_RIGHT = 0b1;
    static readonly BIT_BTN_LEFT = 0b10;

    loc: cc.Vec2 = cc.v2();
    delta: cc.Vec2 = cc.v2();
    lastMsg = "";
    update(evt: cc.Event.EventMouse) {
        let msg = "";
        this.loc = evt.getLocation();
        this.delta = evt.getDelta();

        let btn = evt.getButton();
        switch (evt.type) {
            case "mousemove":
                break;
            case "mouseup":
                if (btn === cc.Event.EventMouse.BUTTON_LEFT) {
                    this.btnLeft = false;
                    msg = "left_up";
                }
                else if (btn === cc.Event.EventMouse.BUTTON_RIGHT) {
                    this.btnRight = false;
                    msg = "right_up";
                }
                break;
            case "mousedown":
                if (btn === cc.Event.EventMouse.BUTTON_LEFT) {
                    this.btnLeft = true;
                    msg = "left_down";
                }
                else if (btn === cc.Event.EventMouse.BUTTON_RIGHT) {
                    this.btnRight = true;
                    msg = "right_down";
                }
                break;
        }
        this.lastMsg = msg;
        return msg;
    }

    get btnLeft() {
        return (this.btn | MouseInfo.BIT_BTN_LEFT) == this.btn;
    }
    set btnLeft(bool) {
        this._setBit(MouseInfo.BIT_BTN_LEFT, bool);
    }
    set btnRight(bool) {
        this._setBit(MouseInfo.BIT_BTN_RIGHT, bool);
    }
    get btnRight() {
        return (this.btn | MouseInfo.BIT_BTN_RIGHT) == this.btn;
    }
};

export class TouchHandle {
    dis = 0;
    loc: cc.Vec2 = null;
    delta: cc.Vec2 = null;
    id: number = 0;

    constructor(id) {
        this.id = id;
    }
};
